﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Reactive.Concurrency;
using System.Reactive.Threading;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Windows.Markup;

using alib;
using alib.Memory;
using alib.file;
using alib.Collections.ReadOnly;
using alib.Debugging;
using alib.Enumerable;
using alib.Reflection;

namespace agree
{
	public class _settings : IReadOnlyDictionary<String, Object>
	{
		public _settings(ApplicationSettingsBase set)
		{
			this.set = set;
		}
		readonly ApplicationSettingsBase set;

		public Object this[String key]
		{
			get
			{
				Object obj;
				return set != null && TryGetValue<Object>(key, out obj) ? obj : null;
			}
			set
			{
				if (set == null)
					return;

				var prop = set.Properties[key];
				if (prop == null)
				{
						var attributes = new SettingsAttributeDictionary();
						var attribute = new UserScopedSettingAttribute();
						attributes.Add(attribute.GetType(), attribute);

						prop = new SettingsProperty(key,
							value.GetType(), 
							set.Providers["LocalFileSettingsProvider"], 
							false,
							null,
							SettingsSerializeAs.String, 
							attributes,
							true,
							true);

						set.Properties.Add(prop);
				}

				set[prop.Name] = value;
			}
		}

		public bool TryGetValue<T>(String key, out T value)
		{
			value = default(T);
			if (set == null)
				return false;

			var prop = set.Properties[key];
			if (prop == null)
				return false;

			var val = set[prop.Name];
			if (val == null || !(val is T))
				return false;

			value = (T)val;
			return true;
		}
		bool IReadOnlyDictionary<String, Object>.TryGetValue(String key, out Object value)
		{
			return TryGetValue<Object>(key, out value);
		}

		public int Count { get { return set == null ? 0 : set.Properties.Count; } }

		public bool ContainsKey(String key) { return set != null && set.Properties[key] != null; }

		public IEnumerable<String> Keys
		{
			get
			{
				if (set == null)
					return alib.Collections.Collection<String>.None;
				throw new NotImplementedException();
			}
		}

		public IEnumerable<object> Values
		{
			get
			{
				if (set == null)
					return alib.Collections.Collection<String>.None;
				throw new NotImplementedException();
			}
		}

		public IEnumerator<KeyValuePair<String, object>> GetEnumerator()
		{
			if (set == null)
				yield break;
			foreach (SettingsProperty x in set.Properties)
				yield return new KeyValuePair<String, Object>(x.Name, set[x.Name]);
		}

		System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}
	};
}
